(function () {
    const kefu = {
        url: '',
        hooks: {},
        config: {
            app_name: '',
            websocket_port: '',
            wss_switch: '',
            not_start_paths: [],
            auto_invitation_switch: '',
            auto_invitation_no_session: '',
            auto_invitation_max: '',
            auto_invitation_timing: '',
            new_message_notification: '',
            click_button_mode: '',
            session_link_dev: '',
            session_link_prod: '',
            ring: '',
        },
        ws: {
            timer: null,
            ready: false,
            errorMsg: [],
            socketTask: null,
            canConnect: true,
            maxReconnectCount: 3, // 最大重连次数
            currentReconnectCount: 0,
        },
        common: {
            userTab: null,
            notificationStatus: false,
        },
        ring: {
            context: new window.AudioContext(),
            source: null,
            buffer: null,
        },
        state: {
            userInfo: {
                id: 0,
                avatar: '',
                nickname: '加载中...',
                identity: 'tourist',
                status: 'offline',
            },
            invitation: {
                count: 0,
                timer: null,
            },
            button: {
                startX: 0,
                startY: 0,
                affixX: 0,
                affixY: 0,
                moveAffixFlag: false,
                clickAffixFlag: false,
            }
        },
        currentUrlObj: new URL(window.location.href),
        initialize: (url, hooks = {}) => {
            kefu.url = url
            kefu.hooks = hooks

            fetch(kefu.tools.url('init'), {
                method: 'GET',
                headers: {
                    'server': '1',
                    'Content-Type': 'application/json'
                }
            }).then((res) => {
                return res.json();
            }).then((data) => {
                if (data.code === 1) {
                    kefu.config = data.data.config

                    // 不启动
                    if (kefu.config.not_start_paths.includes(kefu.currentUrlObj.pathname)) {
                        kefu.hideSystem()
                        return;
                    }

                    // 加载 css
                    kefu.tools.loadCss()

                    // 构建悬浮按钮
                    kefu.tools.button()

                    // 事件注册
                    kefu.eventReg()

                    // 连接 ws
                    kefu.socketConnect()

                    // 一句话欢迎消息
                    if (!kefu.local.get(kefu.cacheKey.BA_KEFU_NEW_USER)) {
                        kefu.onNewMessage(kefu.config.new_user_tip)
                    }

                    typeof kefu.hooks.initSuccess == 'function' && kefu.hooks.initSuccess(kefu.ws, kefu.config)
                } else {
                    console.error(data)
                    kefu.showTip('初始化请求失败！')
                }
            }).catch((err) => {
                console.error(err)
                kefu.showTip('初始化请求失败！')
            })
        },
        hideSystem: () => {
            kefu.hideTip()
            kefu.hideInvitation()
            kefu.hideNewMessagePopover()
            kefu.tools.removeEls('kefu-button')

            kefu.ws.canConnect = false
            if (Object.keys(kefu.state.userInfo).length !== 0) {
                kefu.state.userInfo.status = 'offline'
            }

            kefu.ws.socketTask?.close()
            console.log(`【${kefu.config.app_name}】系统主动关闭，WS将不会自动重新连接`)
        },
        showTip: (message, type = 'info', duration = 3000) => {
            kefu.hideTip()

            const el = document.createElement('div')
            el.innerText = kefu.tools.truncate(message, 16)
            el.className = 'kefu-common-tip kefu-' + type

            const msgWidth = kefu.tools.getStrWidth(el.innerText, 14) + 5
            el.style.width = msgWidth + 'px'
            el.style.left = `calc(50vw - ${msgWidth / 2}px)`

            document.body.appendChild(el)

            if (duration > 0) {
                setTimeout(() => {
                    kefu.hideTip()
                }, duration)
            }
        },
        hideTip: () => {
            kefu.tools.removeEls('kefu-common-tip')
        },
        onNewMessage: (newMessageContent) => {
            // 铃声
            kefu.newMessageRing()

            // WEB Notification
            const notification = kefu.newMessageNotification(newMessageContent, {
                tag: 'ba-kefu-notification',
                renotify: true,
            })
            if (notification) {
                notification.onclick = () => {
                    kefu.onConversation()
                    notification.close()
                }
            }

            // 以下为 popover 的处理
            kefu.hideNewMessagePopover()

            const el = document.createElement('div')
            el.innerText = kefu.tools.truncate(newMessageContent, 16)
            el.className = 'kefu-button-tip'

            const msgWidth = kefu.tools.getStrWidth(el.innerText, 14)
            el.style.width = (msgWidth + 5) + 'px'
            el.style.left = ((msgWidth + 20) * -1) + 'px'
            document.getElementsByClassName('kefu-affix')[0].appendChild(el)
        },
        hideNewMessagePopover() {
            kefu.tools.removeEls('kefu-button-tip')
        },
        autoInvitation: () => {
            // 未开启
            if (kefu.config.auto_invitation_switch !== 'yes') return

            // 已有会话
            if (kefu.state.userInfo.session && kefu.config.auto_invitation_no_session === 'yes') return

            // 最大邀请次数
            if (parseInt(kefu.config.auto_invitation_max) > 0 && kefu.state.invitation.count >= parseInt(kefu.config.auto_invitation_max)) {
                return
            } else {
                kefu.state.invitation.count++
            }

            kefu.state.invitation.timer = window.setTimeout(
                () => {
                    kefu.showInvitation()
                },
                parseInt(kefu.config.auto_invitation_timing) * 1000
            )
        },
        showInvitation: () => {
            if (kefu.state.invitation.timer) {
                clearTimeout(kefu.state.invitation.timer)
            }

            // 会话窗口已打开
            if (kefu.common.userTab && !kefu.common.userTab.closed) return

            // 删除已有的邀请框
            kefu.tools.removeEls('kefu-invitation-box')

            const el = document.createElement('div')
            el.className = 'kefu-invitation-box'
            el.style.background = `url(${kefu.tools.fullUrl(kefu.config.auto_invitation_bg)})`
            el.style.backgroundSize = '100% 100%'
            el.innerHTML = '\
            <div class="kefu-invitation-close">&times;</div>\
            <div class="kefu-invitation-button">\
                <div class="kefu-invitation-button-later">稍后再说</div>\
                <div class="kefu-invitation-button-consulting">现在咨询</div>\
            </div>'

            document.body.appendChild(el)
        },
        hideInvitation: () => {
            kefu.tools.removeEls('kefu-invitation-box')
            kefu.autoInvitation()
        },
        onConversation: () => {
            // 标记新用户态
            if (!kefu.local.get(kefu.cacheKey.BA_KEFU_NEW_USER)) {
                kefu.local.set(kefu.cacheKey.BA_KEFU_NEW_USER, 1)
            }
            const sessionUrl = kefu.currentUrlObj.searchParams.has('dev') ? kefu.config.session_link_dev : kefu.config.session_link_prod
          
            if (kefu.common.userTab && !kefu.common.userTab.closed) {
                kefu.common.userTab.focus()
            } else if (kefu.config.click_button_mode === 'dialog_and_small_window' || kefu.config.click_button_mode === 'small_window') {
                // 会话小窗

                // 小窗 top
                let top = (window.screen.availHeight - 720) / 2
                top = top > 0 ? top : 0

                // 小窗 left
                let left = (window.screen.availWidth - 900) / 2
                left = left > 0 ? left : 0

                kefu.common.userTab = window.open(
                    kefu.tools.addUrlParams(sessionUrl, {
                        mode: 'small',
                        independentTab: 1,
                        baTouristToken: kefu.local.get(kefu.cacheKey.BA_KEFU_TOURIST_TOKEN),
                    }),
                    'dialogueWindow',
                    `height=720,width=900,top=${top},left=${left},toolbar=no,menubar=no,scrollbars=no,resizable=no,location=no,status=no`
                )
            } else if (kefu.config.click_button_mode === 'dialog_and_new_window' || kefu.config.click_button_mode === 'new_window') {
                // 新窗口
                kefu.common.userTab = window.open(
                    kefu.tools.addUrlParams(sessionUrl,
                        {
                            mode: 'new',
                            independentTab: 1,
                            baTouristToken: kefu.local.get(kefu.cacheKey.BA_KEFU_TOURIST_TOKEN),
                        }
                    ),
                    'dialogueWindow'
                )
            }

            // 如果成功打开窗口
            if (kefu.common.userTab) {
                // 隐藏邀请框
                kefu.hideInvitation()

                // 隐藏新消息提示
                kefu.hideNewMessagePopover()
            }
        },
        sendPing() {
            kefu.clearWsTimer()
            kefu.ws.timer = window.setTimeout(() => {
                kefu.socketSend({
                    pathInfo: 'worker/kefu.WsMixed/ping',
                })
            }, 50000)
        },
        socketSend: (message) => {
            if (Object.keys(message).length === 0) {
                return
            }

            if (kefu.ws.socketTask && kefu.ws.socketTask.readyState === 1) {
                kefu.ws.socketTask.send(JSON.stringify(message))
            } else {
                console.log('ws消息发送失败', message)
                kefu.ws.errorMsg.push(message)
            }
        },
        socketConnect: () => {
            if ((kefu.ws.socketTask && (kefu.ws.socketTask.readyState === 0 || kefu.ws.socketTask.readyState === 1)) || !kefu.ws.canConnect) {
                return false
            }

            if (window.location.protocol === 'https:' && kefu.config.wss_switch === 'no') {
                kefu.showTip('https下必须创建wss服务才能连接网络！', 'error', 0)
                return false
            }

            if ('WebSocket' in window) {
                kefu.ws.socketTask = new WebSocket(kefu.tools.url('ws'))

                kefu.ws.socketTask.onopen = () => {
                    // 重新发送所有出错的消息
                    if (kefu.ws.errorMsg.length > 0) {
                        for (const i in kefu.ws.errorMsg) {
                            kefu.socketSend(kefu.ws.errorMsg[i])
                        }
                        kefu.ws.errorMsg = []
                    }

                    // 重置属性
                    kefu.ws.ready = false
                    kefu.ws.currentReconnectCount = 0
                    kefu.hideTip()
                    kefu.clearWsTimer()

                    // 初始化
                    kefu.socketSend({
                        pathInfo: 'worker/kefu.WsIndex/initialize',
                        baUserToken: kefu.currentUrlObj.searchParams.has('token') ? kefu.currentUrlObj.searchParams.get('token') : '',
                        baTouristToken: kefu.local.get(kefu.cacheKey.BA_KEFU_TOURIST_TOKEN),
                    })

                    typeof kefu.hooks.connectionSuccess == 'function' && kefu.hooks.connectionSuccess(kefu.ws, kefu.config)
                }

                kefu.ws.socketTask.onmessage = (evt) => {
                    const msg = JSON.parse(evt.data)
                    kefu.onMessage(msg)
                }

                kefu.ws.socketTask.onclose = () => {
                    kefu.ws.ready = false
                    kefu.clearWsTimer()

                    // 重连
                    kefu.socketReconnect()
                }

                kefu.ws.socketTask.onerror = (e) => {
                    kefu.ws.ready = false
                    console.error('websocket 错误:', e)
                    kefu.showTip('Websocket 发生错误！', 'error', 0)
                }
            } else {
                kefu.showTip('您的浏览器不支持 WebSocket！', 'error', 0)
            }
        },
        socketReconnect: () => {
            if (!kefu.ws.canConnect) {
                return false
            }

            kefu.showTip('网络不给力，正在自动重连。', 'warning', 0)

            if (kefu.ws.currentReconnectCount < kefu.ws.maxReconnectCount) {
                kefu.ws.currentReconnectCount++
                if (kefu.ws.currentReconnectCount === 1) {
                    kefu.socketConnect()
                    console.log('正在重连 WebSocket 第' + kefu.ws.currentReconnectCount + '次')
                } else {
                    console.log('6秒后重连 WebSocket 第' + kefu.ws.currentReconnectCount + '次')
                    kefu.clearWsTimer()
                    kefu.ws.timer = window.setTimeout(() => {
                        kefu.socketConnect()
                        console.log('正在重连 WebSocket 第' + kefu.ws.currentReconnectCount + '次')
                    }, 6000)
                }
            } else {
                // 每18秒重新连接一次
                console.log('18秒后将再次尝试重连 WebSocket')
                kefu.clearWsTimer()
                kefu.ws.timer = window.setTimeout(() => {
                    kefu.socketConnect()
                }, 18000)
            }
        },
        tools: {
            url: (type) => {
                const url = new URL(kefu.url)

                const buildFun = new Map([
                    ['init', () => {
                        return url.origin + '/worker/kefu.HttpIndex/index'
                    }],
                    [
                        'ws',
                        () => {
                            const protocol = kefu.config.wss_switch === 'yes' ? 'wss://' : 'ws://'
                            const port = kefu.config.websocket_port ? ':' + kefu.config.websocket_port : ''

                            const currentUrlParams = kefu.tools.searchParamsToObj(kefu.currentUrlObj.searchParams)
                            const query = {
                                ...currentUrlParams,
                                href: window.location.href,
                            }

                            return kefu.tools.addUrlParams(protocol + url.hostname + port, query)
                        },
                    ],
                    ['ring', () => {
                        return url.origin + '/worker/kefu.HttpIndex/ring?server=1'
                    }],
                    ['css', () => {
                        return url.origin + '/static/kefu/kefu.css'
                    }],
                    [
                        'default',
                        () => {
                            return url.origin
                        },
                    ],
                ])

                const action = buildFun.get(type) || buildFun.get('default')
                return action.call(this)
            },
            addUrlParams(url, params) {
                const urlObj = new URL(url)
                for (const key in params) {
                    urlObj.searchParams.append(key, params[key])
                }
                return urlObj.toString()
            },
            searchParamsToObj(searchParams) {
                let obj = {};
                for (let [key, value] of searchParams.entries()) {
                    if (obj[key]) {
                        obj[key] = [].concat(obj[key], value);
                    } else {
                        obj[key] = value;
                    }
                }
                return obj;
            },
            fullUrl: (url, domain = '') => {
                if (!domain) {
                    const urlObj = new URL(kefu.url)
                    domain = urlObj.origin
                }

                if (!url) {
                    return domain
                }

                const regUrl = new RegExp(/^http(s)?:\/\//)
                const regexImg = new RegExp(/^((?:[a-z]+:)?\/\/|data:image\/)(.*)/i)
                if (!domain || regUrl.test(url) || regexImg.test(url)) {
                    return url
                }
                return domain + url
            },
            truncate: (str, max = 10) => {
                if (str.length > max) {
                    return str.slice(0, max - 3) + '...';
                }
                return str;
            },
            getStrWidth: (str, size) => {
                const _span = document.createElement('span')
                _span.innerText = str
                _span.style.fontSize = size + 'px'
                _span.style.position = 'absolute'
                document.body.appendChild(_span)
                let width = _span.offsetWidth
                document.body.removeChild(_span)
                return width
            },
            removeEls: (className) => {
                const els = document.getElementsByClassName(className)
                for (let i = 0; i < els.length; i++) {
                    els[i].remove()
                }
            },
            loadCss: () => {
                const link = document.createElement('link')
                link.rel = 'stylesheet'
                link.href = kefu.tools.url('css')
                document.head.appendChild(link)
            },
            // 悬浮按钮相关 - s
            button: () => {
                const imgHtml = `<img src="${kefu.tools.fullUrl('/static/kefu/images/affix-1.png')}" alt="${kefu.config.app_name}" class="kefu-button" />`
                const affixDiv = document.createElement('div');
                affixDiv.className = 'kefu-affix'
                affixDiv.innerHTML = imgHtml
                document.body.appendChild(affixDiv)
            },
            buttonPositionUpdate: (top, left) => {
                const el = document.querySelector('.kefu-affix')
                el.style.top = top
                el.style.left = left
            },
            buttonMousedown: (downEl) => {
                kefu.state.button.clickAffixFlag = false
                kefu.state.button.moveAffixFlag = true

                kefu.hideNewMessagePopover()
                document.onselectstart = () => false
                document.ondragstart = () => false
                document.querySelectorAll('iframe').forEach((item) => {
                    item.style.pointerEvents = 'none'
                })

                const e = document.querySelector('.kefu-affix')

                kefu.state.button.affixY = downEl.pageY - e.offsetTop
                kefu.state.button.affixX = downEl.pageX - e.offsetLeft

                // 初始按钮位置记录
                kefu.state.button.startX = parseInt(e.offsetTop)
                kefu.state.button.startY = parseInt(e.offsetLeft)
            },
            buttonMousemove: (moveEl) => {
                if (!kefu.state.button.moveAffixFlag) return

                const e = document.querySelector('.kefu-affix')

                const x = moveEl.pageX - kefu.state.button.affixX
                const y = moveEl.pageY - kefu.state.button.affixY

                const offsetTop = e.offsetTop
                const offsetLeft = e.offsetLeft

                if (Math.abs(kefu.state.button.startY - offsetLeft) + Math.abs(kefu.state.button.startX - offsetTop) > 7) {
                    kefu.state.button.clickAffixFlag = true
                }

                kefu.local.set(kefu.cacheKey.KEFU_BUTTON_COORDINATE, [y, x])
                kefu.tools.buttonPositionUpdate(y + 'px', x + 'px')
            },
            buttonMouseup: () => {
                document.onselectstart = null
                document.ondragstart = null
                document.querySelectorAll('iframe').forEach((item) => {
                    item.style.pointerEvents = 'auto'
                })

                kefu.state.button.moveAffixFlag = false
            },
            // 悬浮按钮相关 - e
        },
        applyNotificationAuth: () => {
            if (Object.keys(kefu.state.userInfo).length === 0) {
                return;
            }

            if (kefu.config.new_message_notification === 'no') return
            if (kefu.config.new_message_notification === 'user' && kefu.state.userInfo.identity === 'csr') return
            if (kefu.config.new_message_notification === 'csr' && kefu.state.userInfo.identity !== 'csr') return

            kefu.common.notificationStatus = false
            const NotificationInstance = Notification || window.Notification
            if (!!NotificationInstance) {
                const permissionNow = NotificationInstance.permission
                if (permissionNow === 'granted') {
                    kefu.common.notificationStatus = true
                } else if (permissionNow === 'default') {
                    // 申请权限
                    NotificationInstance.requestPermission().then((permission) => {
                        if (permission === 'granted') {
                            kefu.common.notificationStatus = true
                        } else if (permission === 'default') {
                            // 用户关闭授权，下次再申请
                        } else {
                            // denied
                            console.log('用户拒绝授权,不能显示 Notification API 通知')
                        }
                    })
                } else {
                    // denied 用户拒绝
                    console.log('用户曾经拒绝显示通知或非https')
                }
            }
        },
        newMessageNotification: (title, options) => {
            if (document.hasFocus()) return false
            if (!kefu.common.notificationStatus) return false

            if (Object.keys(kefu.state.userInfo).length === 0) {
                return;
            }

            if (kefu.config.new_message_notification === 'no') return false
            if (kefu.config.new_message_notification === 'user' && kefu.state.userInfo.identity === 'csr') return false
            if (kefu.config.new_message_notification === 'csr' && kefu.state.userInfo.identity !== 'csr') return false

            const NotificationInstance = Notification || window.Notification
            if (!!NotificationInstance) {
                return new NotificationInstance(title, options)
            } else if ('mozNotification' in navigator) {
                return navigator.mozNotification.createNotification(title, options.body, options.icon).show()
            } else {
                return false
            }
        },
        local: {
            set(key, val) {
                window.localStorage.setItem(key, JSON.stringify(val))
            },
            get(key) {
                const json = window.localStorage.getItem(key)
                return JSON.parse(json)
            },
            remove(key) {
                window.localStorage.removeItem(key)
            },
            clear() {
                window.localStorage.clear()
            },
        },
        cacheKey: {
            BA_KEFU_NEW_USER: 'baKefuNewUser',
            BA_KEFU_TOURIST_TOKEN: 'baKeFuTouristToken',
            KEFU_BUTTON_COORDINATE: 'kefuButtonCoordinate',
        },
        clearWsTimer: () => {
            if (kefu.ws.timer != null) {
                clearTimeout(kefu.ws.timer)
            }
        },
        newMessageRing() {
            if (kefu.config.new_message_sound === 'no' || !kefu.config.ring) return

            if (kefu.ring.buffer) {
                kefu.playRing()
            } else {
                kefu.loadRing()
            }
        },
        playRing() {
            kefu.ring.source = kefu.ring.context.createBufferSource()
            kefu.ring.source.buffer = kefu.ring.buffer
            kefu.ring.source.loop = false
            kefu.ring.source.connect(kefu.ring.context.destination)
            kefu.ring.source.start(0) // 立即播放
        },
        loadRing: () => {
            const url = kefu.tools.url('ring')
            const xhr = new XMLHttpRequest() // 通过XHR下载音频文件
            xhr.open('GET', url, true)
            xhr.responseType = 'arraybuffer'
            xhr.onload = () => {
                // 下载完成
                kefu.ring.context.decodeAudioData(
                    xhr.response,
                    (buffer) => {
                        // 解码成功
                        kefu.ring.buffer = buffer
                        kefu.playRing()
                    },
                    (e) => {
                        console.log('音频解码失败', e)
                    }
                )
            }
            xhr.send()
        },
        eventReg: () => {
            // 恢复按钮位置
            let kefuButtonCoordinate = kefu.local.get(kefu.cacheKey.KEFU_BUTTON_COORDINATE)
            if (kefuButtonCoordinate) {
                if (kefuButtonCoordinate[0] && kefuButtonCoordinate[1] && document.documentElement.clientWidth > parseInt(kefuButtonCoordinate[1])) {
                    kefu.tools.buttonPositionUpdate(kefuButtonCoordinate[0] + 'px', kefuButtonCoordinate[1] + 'px')
                }
            }

            // 窗口大小改动
            window.addEventListener('resize', () => {
                kefu.hideNewMessagePopover()
                kefu.tools.buttonPositionUpdate('80%', 'unset')
            })

            // 滚动条滚动
            window.addEventListener('scroll', () => {
                kefu.hideNewMessagePopover()
            })

            // 按钮拖动
            document.addEventListener('mousemove', kefu.tools.buttonMousemove)
            document.querySelector('.kefu-affix').addEventListener('mousedown', kefu.tools.buttonMousedown)
            document.querySelector('.kefu-affix').addEventListener('mouseup', kefu.tools.buttonMouseup)

            // 全局点击事件监听
            document.addEventListener('click', (e) => {
                // 悬浮按钮
                if (e.target.classList.contains('kefu-button') || e.target.classList.contains('kefu-affix') || e.target.classList.contains('kefu-button-tip')) {
                    if (kefu.state.button.clickAffixFlag) return
                    kefu.onConversation()
                }

                // 邀请框
                if (e.target.classList.contains('kefu-invitation-button-consulting')) {
                    kefu.onConversation()
                }
                if (e.target.classList.contains('kefu-invitation-close') || e.target.classList.contains('kefu-invitation-button-later')) {
                    kefu.hideInvitation()
                }
            })
        },
        onMessage: (msg) => {
            const msgFun = new Map([
                [
                    'pong',
                    () => {
                        // 收到 pong 再设置一个新的计时器来发送下一个心跳，能够尽可能规避浏览器节能导致的连接断开和计时器失准
                        kefu.sendPing()
                    },
                ],
                [
                    'init',
                    () => {
                        if (!msg.data.imUser) {
                            return kefu.hideSystem()
                        }

                        // 缓存游客token
                        if (msg.data.imUser.identity === 'tourist' && msg.data.imUser.token) {
                            kefu.local.set(kefu.cacheKey.BA_KEFU_TOURIST_TOKEN, msg.data.imUser.token)
                        }

                        kefu.state.userInfo = msg.data.imUser
                        typeof kefu.hooks.userInitSuccess == 'function' && kefu.hooks.userInitSuccess(kefu.state.userInfo)

                        // 未读消息通知
                        if (msg.data.imUser.unreadMessage) {
                            kefu.onNewMessage(msg.data.imUser.unreadMessage.formatContent)
                        }

                        // 开始发送心跳
                        kefu.sendPing()

                        // 数据初始化
                        kefu.ws.ready = true
                        kefu.autoInvitation()
                        kefu.applyNotificationAuth()
                    },
                ],
                [
                    'changeStatus',
                    () => {
                        // 当前用户状态改变
                        if (msg.data.id === kefu.state.userInfo.id && msg.data.identity === kefu.state.userInfo.identity) {
                            kefu.state.userInfo.status = msg.data.status
                        }
                    },
                ],
                [
                    'distribution',
                    () => {
                        kefu.state.userInfo.session = msg.data.session.id
                        kefu.onConversation()
                    },
                ],
                [
                    'newMessage',
                    () => {
                        if (msg.data.message.sender_id !== kefu.state.userInfo.id) {
                            // 新消息通知
                            kefu.onNewMessage(msg.data.formatMessage)
                        }

                        // 访客收到强制对话的消息
                        if (kefu.state.userInfo.identity !== 'csr' && !kefu.state.userInfo.session) {
                            kefu.state.userInfo.session = msg.data.session.id
                            kefu.onConversation()
                        }
                    },
                ],
                [
                    'operates',
                    () => {
                        // 收到邀请
                        if (msg.data.operate === 'dialog-invite') {
                            kefu.showInvitation()
                        }
                    },
                ],
                ['readMessage', () => {
                }],
                [
                    'tip',
                    () => {
                        kefu.showTip(msg.data.message, msg.data.type, msg.data.duration)
                    },
                ],
                [
                    'error',
                    () => {
                        kefu.showTip(msg.data.message, 'error', msg.data.duration)
                    },
                ],
                [
                    'close',
                    () => {
                        if (msg.data.message) console.log(msg.data.message)
                        return kefu.hideSystem()
                    },
                ],
                [
                    'default',
                    () => {
                        console.log(msg.data)
                    },
                ],
            ])

            const action = msgFun.get(msg.type) || msgFun.get('default')
            action.call(this)
        },
    };

    window.kefu = kefu
})();